﻿using GalaSoft.MvvmLight;
using System.Collections.ObjectModel;
using DataSentryPro_R2.Model;
using System;
using System.ComponentModel;
using System.Windows.Data;
using GalaSoft.MvvmLight.Command;
using System.Windows;
using System.Diagnostics;

namespace DataSentryPro_R2.ViewModel
{
    /// <summary>
    /// This class contains properties that the main View can data bind to.
    /// <para>
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// <para>
    /// You can also use Blend to data bind with the tool's support.
    /// </para>
    /// <para>
    /// </para>
    /// </summary>
    public class MainViewModel : ViewModelBase
    {

        #region Global Helpers

        // Create a Backgorund Worker To handle DataGrid Updates
        BackgroundWorker worker = new BackgroundWorker(); 


        #endregion



        

        #region View Properties

        #region Private variablies For View Properties

        // Private Vars
        private int _created;
        private int _deleted;
        private int _updated;
        private int _skipped;
        private int _renamed;
        private int _datarate;
        private int _jobsize;
        private int _dataread;
        private string _filextrasfertime;
        private string _elapsedjobtime;
        private string _currentFile;
        private int _fileprogress;
        private int _backupprogress;
        private string _backupsource;
        private string _backuptarget;

        //
        #endregion

        #region Properties
        
        // Ppoperties
        
        public string BackupTarget
        {
            get
            {
                return _backuptarget;
            }

            set
            {
                if (_backuptarget == value)
                {
                    return;
                }

                _backuptarget = value;
            }
        }

        
        public string BackupSource
        {
            get
            {
                return _backupsource;
            }

            set
            {
                if (_backupsource == value)
                {
                    return;
                }

                _backupsource = value;
             
            }
        }

        public const string BackupProgressPropertyName = "BackupProgress"; // Used to Detect Property Changes
        public int BackupProgress
        {
            get
            {
                return _backupprogress;
            }

            set
            {
                if (_backupprogress == value)
                {
                    return;
                }

                _backupprogress = value;
                RaisePropertyChanged(BackupProgressPropertyName);
            }
        }
        
        public int FileProgress
        {
            get
            {
                return _fileprogress;
            }

            set
            {
                if (_fileprogress == value)
                {
                    return;
                }

                _fileprogress = value;
            }
        }
        
        public string CurrentFile
        {
            get
            {
                return _currentFile;
            }

            set
            {
                if (_currentFile == value)
                {
                    return;
                }

                _currentFile = value;
            }
        }
        
        public int JobSize
        {
            get
            {
                return _jobsize;
            }

            set
            {
                if (_jobsize == value)
                {
                    return;
                }

                _jobsize = value;
            }
        }
        
        public int DataRead
        {
            get
            {
                return _dataread;
            }

            set
            {
                if (_dataread == value)
                {
                    return;
                }

                _dataread = value;
            }
        }

        public int DataRate
        {
            get
            {
                return _datarate;
            }

            set
            {
                if (_datarate == value)
                {
                    return;
                }

                _datarate = value;
            }
        }

        
        public string ElepasedJobTime
        {
            get
            {
                return _elapsedjobtime;
            }

            set
            {
                if (_elapsedjobtime == value)
                {
                    return;
                }

                _elapsedjobtime = value;
            }
        }
        
        public string FileTransferTime
        {
            get
            {
                return _filextrasfertime;
            }

            set
            {
                if (_filextrasfertime == value)
                {
                    return;
                }

                _filextrasfertime = value;
            }
        }

        public int Renamed
        {
            get
            {
                return _renamed;
            }

            set
            {
                if (_renamed == value)
                {
                    return;
                }

                _renamed = value;
            }
        }

        public int Skipped
        {
            get
            {
                return _skipped;
            }

            set
            {
                if (_skipped == value)
                {
                    return;
                }

                _skipped = value;
            }
        }   
        public int Updated
        {
            get
            {
                return _updated;
            }

            set
            {
                if (_updated == value)
                {
                    return;
                }

                _updated = value;
            }
        }
        
        public int Deleted
        {
            get
            {
                return _deleted;
            }

            set
            {
                if (_deleted == value)
                {
                    return;
                }

                _deleted = value;
            }
        }

        public int Created
        {
            get
            {
                return _created;
            }

            set
            {
                if (_created == value)
                {
                    return;
                }

                _created = value;
            }
        }




        //
        #endregion




    #endregion


        #region Command Demo Properties


        #region Counter Command


          public const string CounterPropertyName = "Counter"; // Used to Detect Property Changes
          private int _counter; // Used by Dependency Property

        
            public int Counter
            {
                get
                {
                    return _counter;
                }

                set
                {
                    if (_counter == value)
                    {
                        return;
                    }

                    _counter = value;
                    
                    RaisePropertyChanged(CounterPropertyName);
                    SayHelloCommand.RaiseCanExecuteChanged();
                }
            }

        #endregion  





    #endregion



    #region Create Database for Datagrid
        
        // Not using regular Obserbavle Collection because it cannot be updated from another Thread
            
        // Create the Database Object to Bind the View 
        private AsyncObservableCollection<FileFolderItem> _filefolderitems = new AsyncObservableCollection<FileFolderItem>();

        public AsyncObservableCollection<FileFolderItem> FileFolderCatalog  // Collection of Records
        {
            get
            {
                return _filefolderitems;
            }

            set
            {
                if (_filefolderitems == value)
                    return;

                _filefolderitems = value;
                
            }
        }
    #endregion


        public string Welcome
        {
            get
            {
                return "Welcome to MVVM Light";
            }
        }

        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>

        public MainViewModel()
        {
            if (IsInDesignMode)
            {
                // Code runs in Blend --> create design time data.

                // Create Design Time Data

                FileFolderCatalog = new AsyncObservableCollection<FileFolderItem>();

                for (var index = 0; index < 15; index++)
                {
                       var fileFolderItem = new FileFolderItem 
                       {
                           ItemId = index,
                           FileName = "Test"+ index.ToString(),
                           Location = "C:\\SOURCE\\Folder" + index.ToString(),
                           FileSize = index *4,
                           PathSize = index * 2,
                           FileLastAccessed = DateTime.Now,
                           FileLastModified = DateTime.Now,
                           TargetLocation = "D:\\Target\\ocation"+index.ToString(),
                           TargetPathSize = index *5
                       };

                       FileFolderCatalog.Add(fileFolderItem);
                       
                       //  This Collection gives me grouping
                       //ListCollectionView collection = new ListCollectionView(FileFolderCatalog);
                       //collection.GroupDescriptions.Add(new PropertyGroupDescription("Location"));

                       
                }



            }
            else
            {
                // Code runs "for real"

                FileFolderCatalog = new AsyncObservableCollection<FileFolderItem>();

                for (var index = 0; index < 2; index++)
                {
                    var fileFolderItem = new FileFolderItem
                    {
                        ItemId = index,
                        FileName = "Test" + index.ToString(),
                        Location = "C:\\SOURCE\\Folder" + index.ToString(),
                        FileSize = index * 4,
                        PathSize = index * 2,
                        FileLastAccessed = DateTime.Now,
                        FileLastModified = DateTime.Now,
                        TargetLocation = "D:\\Target\\ocation" + index.ToString(),
                        TargetPathSize = index * 5
                    };

                    FileFolderCatalog.Add(fileFolderItem);

                    //  This Collection gives me grouping
                    // ListCollectionView collection = new ListCollectionView(FileFolderCatalog);
                    // collection.GroupDescriptions.Add(new PropertyGroupDescription("Location"));


                }

                    
                // Command Binding


                //TestViewModel viewmodel = this.dataGrid1.DataContext as TestViewModel;
                //viewmodel.ItemsList.Add(new Person() { Name = "cc", Gender = Gender.Male, Age = 22 });
                //viewmodel.ItemsList[0].Name = "new name";

                CancelDataGridUpdates = new RelayCommand(() =>
                {
                    // Cancel The DataGrid Update
                    worker.CancelAsync();



                });



                ModifyFileStats = new RelayCommand(() =>
                {
                    // Grab the DB from the Current DataContext
                    AddFileNamesTest();
                     


                });



                SayHelloCommand = new RelayCommand<string>(
                m =>
                    MessageBox.Show("Hello, " + Counter.ToString()),
                m => _counter % 2 == 0);

                #region Increase Counter Command

                IncreaseCounterCommand = new RelayCommand(() =>
                {
                    Counter++;

                    // Cal the Wasup Function
                    StartLongFileNameCheck();

                });

                #endregion


            }


        }


        #region Command Properties

        public RelayCommand CancelDataGridUpdates
        {
            get;
            private set;
        }


        public RelayCommand ModifyFileStats
        {
            get;
            private set;
        }


        public RelayCommand<string> SayHelloCommand
        {
            get;
            private set;
        }       


        public RelayCommand IncreaseCounterCommand
        {
            get;
            private set;
        }


        #endregion


        #region Long File Name Support Functions


        void AddFileNamesTest()
        {

            int maxRecords = 2000000;

            
            // Enable Cancellation Support for the BW
            // This Worker was created at the class level
            // in order to suppoert cancellation

            worker.WorkerSupportsCancellation = true;
            
            
            worker.DoWork += delegate(object s, DoWorkEventArgs args) 
            
            { 
                
                // Keep Track Of Time
                Stopwatch globalElapsedTime = new Stopwatch();
                
                // Begin
                globalElapsedTime.Start();


                // START

                for (int index = 0; index < maxRecords; index++) 
                { 
                    
                    

                    // Change the Counter Property
                    Counter++;

                    //! Add test Data 
                    var fileFolderItem = new FileFolderItem
                    {
                        ItemId = index,
                        FileName = "Test" + index.ToString(),
                        Location = "C:\\SOURCE\\Folder" + index.ToString(),
                        FileSize = index * 4,
                        PathSize = index * 2,
                        FileLastAccessed = DateTime.Now,
                        FileLastModified = DateTime.Now,
                        TargetLocation = "D:\\Target\\ocation" + index.ToString(),
                        TargetPathSize = index * 5
                    };

                    FileFolderCatalog.Add(fileFolderItem);


                    // Report Progress Every 20 Records
                    if (index % 3 == 0)
                    {
                        // Take  a nap so the UI can Update
                        System.Threading.Thread.Sleep(1);


                        //? Make Sure the BW has not been Cancelled
                        if (worker.CancellationPending)
                        {
                            args.Cancel = true;
                            MessageBox.Show("Process Cancelled");
                            return;

                        }



                    }

                    // Report the Progress of the Job
                    double result = ((double)index / maxRecords)*100;
                    BackupProgress = Convert.ToInt16(result)+1;

                    
                }
               
                // Stop Timer
                globalElapsedTime.Stop();

                MessageBox.Show("It took: " + globalElapsedTime.Elapsed.ToString());

                // END



            
            }; 
            
            



            if(!worker.IsBusy)
                worker.RunWorkerAsync();
         

        }


        void StartLongFileNameCheck()
        {

            MessageBox.Show("Was up!" + Counter.ToString());
        }



        #endregion


        ////public override void Cleanup()
        ////{
        ////    // Clean up if needed

        ////    base.Cleanup();
        ////}
    }
}